﻿using Koala.Pro.Common;
using Koala.Pro.Core;
using Koala.Pro.Core.Dto;
using Koala.Pro.Core.Models;
using SqlSugar;

namespace Koala.Pro.Services
{
    public class BlackIPService : MyCrudService<BlackIPInfo, string, BlackIPPagedDto>, IBlackIPService, IMyCrudService<BlackIPInfo, string, BlackIPPagedDto>, ITransientDependency, IDependency
    {
        public BlackIPService(IApiUserSession currentApiUser)
        {
            base.CurrentApiUser = currentApiUser;
        }

        public override Task<Dictionary<string, string>> GetColumnNameAlias()
        {
            return Task.FromResult(new Dictionary<string, string>
            {
                { "Name", "显示名称" },
                { "AuthorizeType", "授权类型" },
                { "Forbid", "是否禁用" },
                { "IPStart", "IP起始地址" },
                { "IPEnd", "IP结束地址" },
                { "Note", "备注" },
                { "Creator", "创建人" },
                { "Creator_ID", "创建人ID" },
                { "CreateTime", "创建时间" },
                { "Editor", "编辑人" },
                { "Editor_ID", "编辑人ID" },
                { "EditTime", "编辑时间" }
            });
        }

        protected override ISugarQueryable<BlackIPInfo> CreateFilteredQueryAsync(BlackIPPagedDto input)
        {
            return base.CreateFilteredQueryAsync(input).WhereIF(!input.ExcludeId.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.Id != input.ExcludeId).WhereIF(!input.Name.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.Name.Contains(input.Name))
                .WhereIF(input.AuthorizeType.HasValue, (BlackIPInfo s) => s.AuthorizeType == (int?)input.AuthorizeType.Value)
                .WhereIF(input.Forbid.HasValue, (BlackIPInfo s) => s.Forbid == (int?)input.Forbid.Value)
                .WhereIF(!input.IPStart.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.IPStart.Contains(input.IPStart))
                .WhereIF(!input.IPEnd.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.IPEnd.Contains(input.IPEnd))
                .WhereIF(!input.Note.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.Note.Contains(input.Note))
                .WhereIF(!input.Creator.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.Creator.Contains(input.Creator))
                .WhereIF(!input.Creator_ID.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.Creator_ID.Contains(input.Creator_ID))
                .WhereIF(input.CreateTimeStart.HasValue, (BlackIPInfo s) => s.CreateTime >= input.CreateTimeStart.Value)
                .WhereIF(input.CreateTimeEnd.HasValue, (BlackIPInfo s) => s.CreateTime <= input.CreateTimeEnd.Value)
                .WhereIF(!input.Editor.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.Editor.Contains(input.Editor))
                .WhereIF(!input.Editor_ID.IsNullOrWhiteSpace(), (BlackIPInfo t) => t.Editor_ID.Contains(input.Editor_ID))
                .WhereIF(input.EditTimeStart.HasValue, (BlackIPInfo s) => s.EditTime >= input.EditTimeStart.Value)
                .WhereIF(input.EditTimeEnd.HasValue, (BlackIPInfo s) => s.EditTime <= input.EditTimeEnd.Value);
        }

        protected override ISugarQueryable<BlackIPInfo> ApplyDefaultSorting(ISugarQueryable<BlackIPInfo> query)
        {
            return query.OrderBy((BlackIPInfo s) => s.Id);
        }

        public async Task<bool> AddUserAsync(int userID, string blackID)
        {
            BlackIP_UserInfo insertObj = new BlackIP_UserInfo
            {
                User_ID = userID,
                BlackIP_ID = blackID
            };
            return await base.Client.GetSimpleClient<BlackIP_UserInfo>().InsertAsync(insertObj);
        }

        public async Task<List<UserInfo>> GetUsersByBlackIP(string id)
        {
            ISugarQueryable<int> sugarQueryable = from t in base.Client.Queryable((BlackIP_UserInfo t, BlackIPInfo m) => t.BlackIP_ID == m.Id && m.Id == id)
                                                  select t.User_ID;
            List<int> list = sugarQueryable.ToList();
            if (list.Count > 0)
            {
                return await base.Client.GetSimpleClient<UserInfo>().GetListAsync((UserInfo s) => list.Contains(s.Id));
            }
            return new List<UserInfo>();
        }

        public async Task<bool> RemoveUserAsync(int userID, string blackID)
        {
            return await base.Client.GetSimpleClient<BlackIP_UserInfo>().DeleteAsync((BlackIP_UserInfo s) => s.User_ID == userID && s.BlackIP_ID == blackID);
        }

        public List<BlackIPInfo> FindByUser(int userId, AuthorizeType type)
        {
            return (from t in base.Client.Queryable((BlackIPInfo t, BlackIP_UserInfo m) => t.Id == m.BlackIP_ID && m.User_ID == userId && t.AuthorizeType == (int?)(int)type)
                    select (t) into t
                    orderby t.CreateTime
                    select t).ToList();
        }

        public bool ValidateIPAccess(string ipAddress, int userId)
        {
            List<BlackIPInfo> list = FindByUser(userId, AuthorizeType.白名单);
            if (list.Count > 0 && IsInList(list, ipAddress))
            {
                return true;
            }
            List<BlackIPInfo> list2 = FindByUser(userId, AuthorizeType.黑名单);
            if (list2.Count > 0)
            {
                return !IsInList(list2, ipAddress);
            }
            return true;
        }

        private bool IsInList(List<BlackIPInfo> list, string ip)
        {
            if (!string.IsNullOrEmpty(ip))
            {
                foreach (BlackIPInfo item in list)
                {
                    if (NetworkUtil.IsInIp(ip, item.IPStart, item.IPEnd))
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    }
}
